/*
 * @Description: Modal Table 逻辑
 * @Author: James324
 * @Date: 2023-09-03 22:59:47
 * @LastEditors: James324
 * @LastEditTime: 2024-03-09 09:23:42
 */
import Modal from '@/components/q-modal/index.vue';
import { deepUnRef, deepClone } from '@/utils';
import { isEqual } from 'lodash-es';
type Fn = (args?: any) => Promise<any>;
type ValidFn = () => boolean | undefined;

/**
 * @param {ValidFn} 自定义校验函数
 */
interface Params {
    validFn?: ValidFn;
    data?: anyObj; // 监听自定义数据
    appendData?: anyObj; // 监听表格之外的数据
    excludeKey?: Ref<string[]>; // 新增时表格数组长度为0 需要排除掉监听
}
const defaultParams = { validFn: () => true };
export default function useModal({
    validFn,
    data,
    appendData = {},
    excludeKey = ref([])
}: Params = defaultParams) {
    const modalSlotRef = ref();
    const visible = ref(false);
    const loading = ref(false);
    const fullscreen = ref(false);

    /**
     * 点击 Modal 确认按钮
     * @param {boolean} closeValid 关闭表格自带校验
     */
    const modalOk = async (fn: Fn, closeValid?: boolean) => {
        // 判断是否更改如果没有更改直接通过
        const unUpdate = isUnUpdate();
        if (unUpdate) {
            visible.value = false;
            return Promise.resolve();
        }

        const { handleValidFieldPass, setInit } = modalSlotRef.value
            ? modalSlotRef.value
            : { handleValidFieldPass: validFn, setInit: () => {} };

        if (!closeValid && !handleValidFieldPass()) return Promise.reject('验证不通过');

        try {
            loading.value = true;
            const res = await fn();

            if (typeof setInit === 'function') setInit(true);
            if (res) {
                visible.value = false;
                return Promise.resolve();
            }

            return Promise.reject('未返回结果');
        } catch (error) {
            console.error(error);
            return Promise.reject(error);
        } finally {
            loading.value = false;
        }
    };

    // 需要监听的数据
    const watchData = computed(() => {
        if (data) return { data };
        return { tableData: modalSlotRef.value?.tableData, appendData };
    });

    /**
     * @: 判断数据是否为空
     */
    const isEmpty = computed(() => {
        for (const key in deepUnRef(watchData.value)) {
            if (excludeKey.value.includes(key)) return false;
            const item = deepUnRef(watchData.value)[key];
            if (
                // key 为表格数据才做数组长度判断，避免影响其他数据发生变化不向后端发送请求
                (key === 'tableData' && Array.isArray(item) && item.length === 0) ||
                item === undefined
            ) {
                return true;
            }
        }
        return false;
    });

    let preData: any = null;

    // 是否在初始化
    let initializing = true;
    // 弹窗关闭时初始化更新状态
    watch(visible, () => {
        if (!visible.value) {
            preData = null;
            flag = 0;
        } else {
            initializing = true;
            init();
        }
    });

    // 初始化数据
    let flag = 0;
    const init = () => {
        if (!isEmpty.value) {
            setTimeout(() => {
                initializing = false;
                preData = deepClone(watchData.value);
            }, 600);

            // 数据超过10秒未返回则会断开连接
        } else if (flag < 110 && isEmpty.value) {
            flag++;
            setTimeout(() => {
                init();
            }, 100);
        }
    };

    /**
     * 点击 Modal 取消
     */
    let isSave: boolean;
    const setIsSave = (val: boolean) => (isSave = val);
    const handleCancel = (directClose: boolean | Event) => {
        const unUpdate = isUnUpdate();
        // 如果在初始化中 或者没有更改直接关闭
        if ((typeof directClose === 'boolean' && directClose) || unUpdate) {
            // 直接关闭，不做二次确认
            visible.value = false;
        } else {
            Modal.confirm({
                title: '数据未保存，确定取消吗？',
                content: '取消后将会放弃本次填写的内容',
                afterClose: () => {
                    if (isSave) visible.value = false;

                    setIsSave(false);
                },
                onOk: () => {
                    setIsSave(true);
                }
            });
        }
    };

    /* 全屏事件 */
    const handleFullscreen = (expand: boolean) => {
        fullscreen.value = expand;
    };

    /**
     * @: 通过flag判断新增或者编辑
     */
    const isUnUpdate = () => {
        const currentData = deepClone(watchData.value);
        return flag ? initializing || isEqual(currentData, preData) : isEqual(currentData, preData);
    };

    /* 表格最大高度 */
    const getMaxHeight = () => {
        return computed(() => (fullscreen.value ? '100%' : 350)).value;
    };

    return {
        modalSlotRef,
        loading,
        modalOk,
        visible,
        handleCancel,
        handleFullscreen,
        fullscreen,
        getMaxHeight
    };
}
